package empty.dsa.arch
import empty.dsa.util.ADL.{ModuleTrace,EleTrace}
import empty.dsa.util.dsaParam._
import empty.dsa.util.EleType._

class sha1_top (dsa : dsa_Param, set_width: Int) extends ModuleTrace ("sha1" + dsa.PE_num){

  this.typeStr = "dsa"
  this.deviceStr = "sha1_" + dsa.PE_num + "PE_dsa"
  this.width = set_width

  //添加输入
  val inPortsList = (0 until dsa.IB_num).map("in" + _.toString).toList
  this.inPorts = inPortsList

  //LM: 添加输出
  val outPortsList = (0 until dsa.OB_num).map("out" + _.toString).toList
  this.outPorts = outPortsList

  //添加PE
  for(i <- 0 until dsa.PE_num) {
    addModule(PE(dsa.peParams(i),"PE" + i.toString))
  }

  //LM: 添加IB
  for(i <- 0 until dsa.IB_num) {
    val IB = new EleTrace("IB" + i.toString, TYPE_IB.id, List("in0"), List("out0"), List( width))
    addEle(IB)
  }

  //LM: 添加OB
  for(i <- 0 until dsa.OB_num) {
    val OB = new EleTrace("OB" + i.toString, TYPE_OB.id, List("in0"), List("out0"), List(1, width))
    addEle(OB)
  }

  //添加DPM
  val inList = for (i <- 0 until 16) yield {
    "in" + i
  }
  val outList = for (i <- 0 until dsa.PE_num) yield {
    "out" + i
  }
  val DPM = new EleTrace("DPM", TYPE_DPM_sha1.id, inList.toList, outList.toList, List(16, dsa.PE_num, 32))
  addEle(DPM)

  //添加PE.out和OB之间的连接
  for(i <- 0 until dsa.OB_num) {
    addConnect(("PE" + (dsa.PE_num - 1), "out" + i.toString), ("OB" + i.toString, "in0"))
  }

  //添加PE之间的连接
  for(j <- 0 until dsa.PE_num - 1) {
    for(i <- 0 until 6) {
      addConnect(("PE" + j.toString, "out" + i.toString), ("PE" + (j + 1).toString, "in" + i.toString))
    }
  }

  if(dsa.PE_num < 80) {
    for(i <- 0 until 6) {
      addConnect(("PE" + (dsa.PE_num - 1), "out" + i.toString), ("PE0", "in" + i.toString))
    }
  }

  //添加IB和DPM之间的连接
  for(i <- 0 until dsa.IB_num) {
    addConnect(("IB" + i.toString, "out0"), ("DPM", "in" + i.toString))
  }

  //添加DPM和PE之间的连接
  for(i <- 0 until dsa.PE_num) {
    addConnect(("DPM", "out" + i.toString), ("PE" + i.toString, "in6"))
  }

  //添加输入与IB之间的连接
  for(i <- 0 until dsa.IB_num) {
    addConnect(("this", "in" + i.toString), ("IB" + i.toString, "in0"))
  }

  //添加输出与OB之间的连接
  for(i <- 0 until dsa.OB_num) {
    addConnect(("OB" + i.toString, "out0"), ("this", "out" + i.toString))
  }



}

object sha1_dsaGen {

  val pe_num = 80
  val width = 32
  val in_num = 16
  val out_num = 5
  val paramList = for (i <- 1 to pe_num) yield List(width, pe_num, i)
  val pe_p = for (i <- 0 until pe_num) yield {
    val peIndex = "PE" + i
    val aluIndex = "ALU" + i
    val aluParam = alu_Param("sha1", 7, 6, paramList(i), aluIndex)
    PEParam(width, peIndex, 1, List(aluParam))
  }

  val sha1_dsaModule = new sha1_top(dsa_Param(pe_num, in_num, out_num, pe_p.toList), width).getModuleInfo()

}

//object sha1_dsaGenApp extends App {
//  chisel3.Driver.execute(args, () => topGen(sha1_dsaGen.sha1_dsaModule, "sha1_" + sha1_dsaGen.pe_num  + ".txt"))
//  dumpIR(sha1_dsaGen.sha1_dsaModule, "sha1_" + sha1_dsaGen.pe_num + ".xml", "sha1_" + sha1_dsaGen.pe_num)
//
//}